# vim:set ft= ts=4 sw=4 et fdm=marker:

use Test::Nginx::Socket::Lua;


plan tests => repeat_each() * (blocks() * 3);


our $http_config = <<'_EOC_';
    lua_package_path "${prefix}../../script/?.ljbc;${prefix}../../script/?.lua;;";
_EOC_

no_shuffle();
# no_long_string();

run_tests();

__DATA__


=== TEST 1: plain object
--- http_config eval: $::http_config
--- config
        location = /t {
            content_by_lua_block {
                local RES
                do
                    local mapper = require("shared.object.mapper")

                    local input  = {
                        balance        = "balance_value",
                        currency       = "currency_value",
                        src_balance    = "src_balance_value",
                        src_currency   = "src_currency_value",
                        _timestamp     = "_timestamp_value",
                    }

                    local res = mapper.map(input, {
                        balance    = "src_balance",
                        currency   = "src_currency",
                        _timestamp = "_timestamp",
                    })

                    -- export
                    RES = res
                end

                local EXPECT = {
                    balance    = "src_balance_value",
                    currency   = "src_currency_value",
                    _timestamp = "_timestamp_value",
                }

                for k, v in pairs(EXPECT) do
                    if v ~= RES[k] then
                        assert(false, string.format("expect: %s, actural: %s", v, RES[k]))
                    end
                end
            }
        }
--- request
GET /t
--- response_body
--- error_code: 200
--- no_error_log
[error]



=== TEST 2: ScalarMapper
--- http_config eval: $::http_config
--- config
        location = /t {
            content_by_lua_block {
                local RES
                do
                    local mapper = require("shared.object.mapper")

                    local input  = {
                        balance        = "balance_value",
                        currency       = "currency_value",
                        src_balance    = "src_balance_value",
                        src_currency   = "src_currency_value",
                        _timestamp     = "_timestamp_value",
                    }

                    local res = mapper.map(input, {
                        balance    = mapper.ScalarMapper("src_balance"),
                        currency   = mapper.ScalarMapper("src_currency"),
                        _timestamp = mapper.ScalarMapper("_timestamp"),
                    })

                    -- export
                    RES = res
                end

                local EXPECT = {
                    balance    = "src_balance_value",
                    currency   = "src_currency_value",
                    _timestamp = "_timestamp_value",
                }

                for k, v in pairs(EXPECT) do
                    if v ~= RES[k] then
                        assert(false, string.format("expect: %s, actural: %s", v, RES[k]))
                    end
                end
            }
        }
--- request
GET /t
--- response_body
--- error_code: 200
--- no_error_log
[error]



=== TEST 3: ObjectMapper
--- http_config eval: $::http_config
--- config
        location = /t {
            content_by_lua_block {
                local RES
                do
                    local mapper = require("shared.object.mapper")

                    local input  = {
                        balance        = "balance_value",
                        currency       = "currency_value",
                        src_balance    = "src_balance_value",
                        src_currency   = "src_currency_value",
                        src_invoice    = {
                            src_number = "123456",
                            number     = "--",
                        },
                        _timestamp     = "_timestamp_value",
                    }

                    local res = mapper.map(input, {
                        balance    = "src_balance",
                        currency   = "src_currency",
                        invoice    = mapper.ObjectMapper("src_invoice", {
                            number = "src_number",
                        }),
                        _timestamp = "_timestamp",
                    })

                    -- export
                    RES = res
                end

                local EXPECT = {
                    balance    = "src_balance_value",
                    currency   = "src_currency_value",
                    invoice    = {
                        number = "123456",
                    },
                    _timestamp = "_timestamp_value",
                }

                for k, v in pairs(EXPECT) do
                    if type(v) ~= "table" then
                        if v ~= RES[k] then
                            assert(false, string.format("expect: %s, actural: %s", v, RES[k]))
                        end
                    else
                        if k == "invoice" then
                            local invoice = RES[k]
                            for kk, vv in pairs(v) do
                                if vv ~= invoice[kk] then
                                    assert(false, string.format("expect: %s, actural: %s", vv, invoice[kk]))
                                end
                            end
                        end
                    end
                end
            }
        }
--- request
GET /t
--- response_body
--- error_code: 200
--- no_error_log
[error]



=== TEST 4: ListMapper
--- http_config eval: $::http_config
--- config
        location = /t {
            content_by_lua_block {
                local RES
                do
                    local mapper = require("shared.object.mapper")

                    local input  = {
                        invoices = {
                            {
                                src_number = "88123456",
                                number     = "--",
                            },
                            {
                                src_number = "88223456",
                                number     = "--",
                            },
                        },
                        src_invoices = {
                            {
                                src_number = "123456",
                                number     = "--",
                            },
                            {
                                src_number = "223456",
                                number     = "--",
                            },
                        },
                        _timestamp     = "_timestamp_value",
                    }

                    local res = mapper.map(input, {
                        invoices  = mapper.ListMapper("src_invoices", {
                            number = "src_number",
                        }),
                        _timestamp = "_timestamp",
                    })

                    -- export
                    RES = res
                end

                local EXPECT = {
                    invoices = {
                        {
                            number = "123456",
                        },
                        {
                            number = "223456",
                        },
                    },
                    _timestamp = "_timestamp_value",
                }

                for k, v in pairs(EXPECT) do
                    if type(v) ~= "table" then
                        if v ~= RES[k] then
                            assert(false, string.format("expect: %s, actural: %s", v, RES[k]))
                        end
                    else
                        if k == "invoices" then
                            for i, elem in ipairs(v) do
                                local item = RES[k][i]
                                assert(item, string.format("item[%d] should not nil", i))

                                for kk, vv in pairs(elem) do
                                    if vv ~= item[kk] then
                                    assert(false, string.format("expect: %s, actural: %s", vv, item[kk]))
                                    end
                                end
                            end
                        end
                    end
                end
            }
        }
--- request
GET /t
--- response_body
--- error_code: 200
--- no_error_log
[error]



=== TEST 5: plain object to nested object
--- http_config eval: $::http_config
--- config
        location = /t {
            content_by_lua_block {
                local RES
                do
                    local mapper = require("shared.object.mapper")

                    local input  = {
                        name        = "luffy",
                        alias       = "lucy",
                        age         = 19,
                        affiliation = "Straw Hat Pirates",
                        origin      = "East Blue",
                    }

                    local res = mapper.map(input, {
                        name        = "name",
                        affiliation = "affiliation",
                        details = {
                            age    = "age",
                            alias  = "alias",
                            origin = "origin",
                        },
                    })

                    -- export
                    RES = res
                end

                local EXPECT = {
                    name        = "luffy",
                    affiliation = "Straw Hat Pirates",
                    details = {
                        alias  = "lucy",
                        age    = 19,
                        origin = "East Blue",
                    },
                }

                for k, v in pairs(EXPECT) do
                    if type(v) ~= "table" then
                        if v ~= RES[k] then
                            assert(false, string.format("expect: %s, actural: %s", v, RES[k]))
                        end
                    else
                        if k == "details" then
                            local details = RES[k]
                            for kk, vv in pairs(v) do
                                if vv ~= details[kk] then
                                    assert(false, string.format("expect: %s, actural: %s", vv, details[kk]))
                                end
                            end
                        end
                    end
                end
            }
        }
--- request
GET /t
--- response_body
--- error_code: 200
--- no_error_log
[error]



=== TEST 6: ListMapper (use ListMapper from root)
--- http_config eval: $::http_config
--- config
        location = /t {
            content_by_lua_block {
                local RES
                do
                    local mapper = require("shared.object.mapper")

                    local input  = {
                        {
                            src_number = "88123456",
                            number     = "--",
                        },
                        {
                            src_number = "88223456",
                            number     = "--",
                        },
                    }

                    local res = mapper.map(input, {
                        invoices  = mapper.ListMapper(nil, {
                            number = "src_number",
                        })
                    })

                    -- export
                    RES = res
                end

                local EXPECT = {
                    invoices = {
                        {
                            number = "88123456",
                        },
                        {
                            number = "88223456",
                        },
                    }
                }

                for k, v in pairs(EXPECT) do
                    if type(v) ~= "table" then
                        if v ~= RES[k] then
                            assert(false, string.format("expect: %s, actural: %s", v, RES[k]))
                        end
                    else
                        if k == "invoices" then
                            for i, elem in ipairs(v) do
                                local item = RES[k][i]
                                assert(item, string.format("item[%d] should not nil", i))

                                for kk, vv in pairs(elem) do
                                    if vv ~= item[kk] then
                                    assert(false, string.format("expect: %s, actural: %s", vv, item[kk]))
                                    end
                                end
                            end
                        end
                    end
                end
            }
        }
--- request
GET /t
--- response_body chomp
--- error_code: 200
--- no_error_log
[error]


